package cn.mumzone.pos.util.print;

import android.app.PendingIntent;
import android.app.Service;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.hardware.usb.UsbConstants;
import android.hardware.usb.UsbDevice;
import android.hardware.usb.UsbDeviceConnection;
import android.hardware.usb.UsbEndpoint;
import android.hardware.usb.UsbInterface;
import android.hardware.usb.UsbManager;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.text.TextUtils;


import com.minipos.device.CashDrawer;
import com.minipos.device.Printer;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Vector;

import cn.mumzone.basic.util.AppDateUtil;
import cn.mumzone.basic.util.BigDecimalUtil;
import cn.mumzone.basic.util.DeviceIdUtils;
import cn.mumzone.basic.util.ListUtil;
import cn.mumzone.basic.util.SPManager;
import cn.mumzone.basic.util.StringUtils;
import cn.mumzone.basic.util.ToastUtil;
import cn.mumzone.basic.util.log.Elog;
import cn.mumzone.pos.AppConstants;
import cn.mumzone.pos.BuildConfig;
import cn.mumzone.pos.model.OffWorkTicketEntity;
import cn.mumzone.pos.model.RechargeDetailEntity;
import cn.mumzone.pos.model.source.AppRepository;
import cn.mumzone.pos.util.AppUtil;
import cn.mumzone.pos.util.BillUtil;

import static cn.mumzone.basic.util.StringUtils.getFormattedMoney;

/**
 * author: lijiateng
 * created on: 17/11/26 下午2:40
 * description: 打印机服务
 */
public class PrinterService extends Service {

    private static final String ACTION_USB_PERMISSION = "com.usb.printer.USB_PERMISSION";
    public static final String ACTION_DO_PRINT = "action.do.doPrintWork." + BuildConfig.APPLICATION_ID;
    public static final String ACTION_DO_PRINT_OFFWORD = "action.do.doPrintWork.offWord" + BuildConfig.APPLICATION_ID;
    public static final String ACTION_DO_PRINT_RECHARGE = "action.do.doPrintWork.recharge" + BuildConfig.APPLICATION_ID;
    public static final String ACTION_DO_OPEN_DRAWER = "action.do.doOpenDrawer" + BuildConfig.APPLICATION_ID;
    public static final String PRINT_COUNT = "print_count";
    public static final String PRINT_FLAVOR = "print_flavor";

    private static final int PRINT_TYPE_BILL = 3001;
    private static final int PRINT_TYPE_OFF_WORK = 3002;
    private static final int PRINT_TYPE_RECHARGE = 3003;

    private static final String PRINT_LINE = "--------------------------------\n";

    public static final short PRINT_MAX_LENGTH = 32;
    public static final short PRINT_GOODS_NAME_LENGTH = 12;
    public static final short PRINT_GOODS_PRICE_LENGTH = 8;
    public static final short PRINT_GOODS_COUNT_LENGTH = 4;

    public static final short PRINT_SALE_TYPE_LENGTH = 10;
    public static final short PRINT_SALE_PRICE_LENGTH = 9;

    public static final String PRINT_TAG = "Printer";


    public static final short PRINT_UNIT = 43;

    private Context mContext;
    private UsbDevice mUsbDevice;
    private PendingIntent mPermissionIntent;
    private UsbManager mUsbManager;
    private UsbDeviceConnection mUsbDeviceConnection;

    public PrinterService() {
//        super("PrinterService");
    }

//    @Override
//    protected void onHandleIntent(@Nullable Intent intent) {
//        printData = intent.getStringExtra(ACTION_DO_PRINT);
//        init(getApplicationContext());
//    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        init(getApplicationContext());

        return super.onStartCommand(intent, flags, startId);
    }

    private void init(Context context) {

        // 初始化打印机
        initPrinter(context);

        // 为打印机申请打印权限
        requestPermissionForPrinter();

    }

    /**
     * 初始化打印机
     *
     * @param context
     */
    private void initPrinter(Context context) {
        mContext = context;
        mUsbManager = (UsbManager) mContext.getSystemService(Context.USB_SERVICE);

        // 设置 PendingIntent
        mPermissionIntent = PendingIntent.getBroadcast(mContext, 0, new Intent(ACTION_USB_PERMISSION), 0);
        IntentFilter filter = new IntentFilter(ACTION_USB_PERMISSION);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_ATTACHED);
        filter.addAction(UsbManager.ACTION_USB_DEVICE_DETACHED);
        filter.addAction(PrinterService.ACTION_DO_PRINT);
        filter.addAction(PrinterService.ACTION_DO_PRINT_OFFWORD);
        filter.addAction(PrinterService.ACTION_DO_PRINT_RECHARGE);
        filter.addAction(PrinterService.ACTION_DO_OPEN_DRAWER);

        // 注册广播
        mContext.registerReceiver(mUsbDeviceReceiver, filter);
    }

    private final BroadcastReceiver mUsbDeviceReceiver = new BroadcastReceiver() {
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Elog.e(PRINT_TAG, " 接收广播  action-->" + action + "      渠道包 -->" + BuildConfig.FLAVOR);
            if (ACTION_USB_PERMISSION.equals(action)) {

                // 获取打印机权限的回调
                synchronized (this) {
                    UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (intent.getBooleanExtra(UsbManager.EXTRA_PERMISSION_GRANTED, false)) {
                        mUsbDevice = usbDevice;
                    } else {
                        ToastUtil.makeText(context, "无打印权限，请重新连接打印机！", true);
                    }
                }

            } else if (ACTION_DO_PRINT.equals(action)) {

                // 执行打印
                if (mUsbDevice != null) {
                    String flavor = intent.getStringExtra(PRINT_FLAVOR);
                    if (!StringUtils.isEmpty(flavor) && !flavor.equals(BuildConfig.FLAVOR)) {
                        return;
                    }
                    PrintEntity printData = (PrintEntity) intent.getSerializableExtra(ACTION_DO_PRINT);
                    int printCount = intent.getIntExtra(PRINT_COUNT, 2);
                    if (printData == null) {
                        ToastUtil.makeText(mContext, "打印数据格式异常", false);
                        return;
                    }
                    Elog.e(PRINT_TAG, "准备打印小票  渠道包 -->" + flavor + "  打印次数 -->" + printCount);
                    doPrintWork(PRINT_TYPE_BILL, printData, printCount);
                }

            } else if (ACTION_DO_PRINT_OFFWORD.equals(action)) {

                // 执行打印
                if (mUsbDevice != null) {
                    String flavor = intent.getStringExtra(PRINT_FLAVOR);
                    if (!StringUtils.isEmpty(flavor) && !flavor.equals(BuildConfig.FLAVOR)) {
                        return;
                    }
                    OffWorkTicketEntity ticketEntity = (OffWorkTicketEntity) intent.getSerializableExtra(ACTION_DO_PRINT_OFFWORD);
                    int prientCount = intent.getIntExtra(PRINT_COUNT, 2);
                    if (ticketEntity == null) {
                        ToastUtil.makeText(mContext, "打印数据格式异常", false);
                        return;
                    }
                    Elog.e(PRINT_TAG, "准备打印小票  渠道包 -->" + flavor + "  打印次数 -->" + prientCount);
                    doPrintWork(PRINT_TYPE_OFF_WORK, ticketEntity, prientCount);
                }

            } else if (ACTION_DO_PRINT_RECHARGE.equals(action)) {

                // 执行打印
                if (mUsbDevice != null) {
                    String flavor = intent.getStringExtra(PRINT_FLAVOR);
                    if (!StringUtils.isEmpty(flavor) && !flavor.equals(BuildConfig.FLAVOR)) {
                        return;
                    }
                    RechargeDetailEntity ticketEntity = (RechargeDetailEntity) intent.getSerializableExtra(ACTION_DO_PRINT_RECHARGE);
                    int prientCount = intent.getIntExtra(PRINT_COUNT, 2);
                    if (ticketEntity == null) {
                        ToastUtil.makeText(mContext, "打印数据格式异常", false);
                        return;
                    }
                    Elog.e(PRINT_TAG, "准备打印小票  渠道包 -->" + flavor + "  打印次数 -->" + prientCount);
                    doPrintWork(PRINT_TYPE_RECHARGE, ticketEntity, prientCount);
                }

            } else if (ACTION_DO_OPEN_DRAWER.equals(action)) {
                // 打开钱箱
                String flavor = intent.getStringExtra(PRINT_FLAVOR);
                if (!StringUtils.isEmpty(flavor) && !flavor.equals(BuildConfig.FLAVOR)) {
                    return;
                }
                Elog.e(PRINT_TAG, "准备打开钱箱  渠道包 -->" + flavor);
                openDrawer();

            } else {
                if (UsbManager.ACTION_USB_DEVICE_DETACHED.equals(action)) {

                    // 打印机断开的回调

                    UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (usbDevice.getInterface(0).getInterfaceClass() == UsbConstants.USB_CLASS_PRINTER) {
                        ToastUtil.makeText(context, "打印机已断开,请检查！", true);
                        destroy();
                    } else if (usbDevice.getInterface(0).getInterfaceClass() == UsbConstants.USB_CLASS_HID) {
                        ToastUtil.makeText(context, "扫码枪已断开", true);
                    }

                } else if (UsbManager.ACTION_USB_DEVICE_ATTACHED.equals(action)) {
                    UsbDevice usbDevice = intent.getParcelableExtra(UsbManager.EXTRA_DEVICE);
                    if (usbDevice.getInterface(0).getInterfaceClass() == UsbConstants.USB_CLASS_PRINTER) {
                        ToastUtil.makeText(context, "打印机已连接", true);
                        // 检测到设备插入的回调，申请打印权限
                        requestPermissionForPrinter();
                    } else if (usbDevice.getInterface(0).getInterfaceClass() == UsbConstants.USB_CLASS_HID) {
                        ToastUtil.makeText(context, "扫码枪已连接", true);
                    }


                }
            }
        }
    };


    /**
     * 为打印机申请权限
     */
    private void requestPermissionForPrinter() {
        if (mUsbManager != null) {
            HashMap<String, UsbDevice> deviceList = mUsbManager.getDeviceList();
            for (UsbDevice device : deviceList.values()) {
                if (device.getInterface(0).getInterfaceClass() == UsbConstants.USB_CLASS_PRINTER) {
                    if (!mUsbManager.hasPermission(device)) {
                        mUsbManager.requestPermission(device, mPermissionIntent);
                    } else {
                        mUsbDevice = device;
                    }
                }
            }
        }
    }

    public void doPrintWork(final int type, final Object data, final int printCount) {
        Elog.e(PRINT_TAG, "准备打印小票  POS机型号 -->" + AppConstants.TEMP_EQUI_MODEL);
        if (AppUtil.isBaoYingPos()) {
            Printer prt = null;
            try {
                EscCommand esc = new EscCommand();
                esc.addInitializePrinter();
                esc.addSelectKanjiMode();
                for (int index = 0; index < printCount; index++) {

                    switch (type) {
                        case PRINT_TYPE_BILL:
                            addBillTemp(esc, (PrintEntity) data);
                            break;
                        case PRINT_TYPE_OFF_WORK:
                            addOffWordTemp(esc, (OffWorkTicketEntity) data);
                            break;
                        case PRINT_TYPE_RECHARGE:
                            addRechargeTemp(esc, (RechargeDetailEntity) data);
                            break;

                    }
                }
                Vector<Byte> datas = esc.getCommand(); // 发送数据
                byte[] bytes = GpUtils.ByteTo_byte(datas);
                prt = Printer.newInstance();

                if (!prt.ready()) {
                    ToastUtil.makeText(mContext, "打印机未准备就绪!", false);
                    return;
                }
                prt.getOutputStream().write(bytes);

                if (prt.ready()) {
                    Elog.e(PRINT_TAG, "打印完成   打印内容 --->" + datas.toString());
                }

            } catch (Throwable throwable) {
                throwable.printStackTrace();
            } finally {
                if (prt != null) {
                    prt.close();
                }
            }
        } else if (AppUtil.isSunMiPos()) {
            if (mUsbDevice != null) {
                UsbInterface usbInterface = mUsbDevice.getInterface(0);
                for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
                    final UsbEndpoint usbEndpoint = usbInterface.getEndpoint(i);
                    if (usbEndpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                        if (usbEndpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
                            mUsbDeviceConnection = mUsbManager.openDevice(mUsbDevice);
                            if (mUsbDeviceConnection != null) {
                                mUsbDeviceConnection.claimInterface(usbInterface, true);
                                new Thread(new Runnable() {
                                    @Override
                                    public void run() {
                                        EscCommand esc = new EscCommand();
                                        esc.addInitializePrinter();
                                        for (int index = 0; index < printCount; index++) {

                                            switch (type) {
                                                case PRINT_TYPE_BILL:
                                                    addBillTemp(esc, (PrintEntity) data);
                                                    break;
                                                case PRINT_TYPE_OFF_WORK:
                                                    addOffWordTemp(esc, (OffWorkTicketEntity) data);
                                                    break;
                                                case PRINT_TYPE_RECHARGE:
                                                    addRechargeTemp(esc, (RechargeDetailEntity) data);
                                                    break;

                                            }
                                        }
                                        Vector<Byte> datas = esc.getCommand(); // 发送数据
                                        byte[] bytes = GpUtils.ByteTo_byte(datas);

                                        int b = mUsbDeviceConnection.bulkTransfer(usbEndpoint, bytes, bytes.length, 3000);
                                        Elog.e(PRINT_TAG, "打印完成  " + "   打印内容 --->" + datas.toString() + "  打印长度 -->" + b);
                                    }
                                }).start();
                            }
                            break;
                        }
                    }
                }
            } else {
                ToastUtil.makeText(mContext, "打印机已断开,请检查！", true);
            }
        }

    }


    private void openDrawer() {

//      宝盈POS打开钱箱
        Elog.e(PRINT_TAG, "准备打开钱箱  POS机型号 -->" + AppConstants.TEMP_EQUI_MODEL);

        if (AppUtil.isBaoYingPos()) {
            try {
                CashDrawer cashDrawer = CashDrawer.newInstance();
                cashDrawer.kickOutPin2(100);
                Elog.e(PRINT_TAG, "打开钱箱成功");
            } catch (Throwable throwable) {
                throwable.printStackTrace();
            }
        } else if (AppUtil.isSunMiPos()) {
            if (mUsbDevice != null) {
                UsbInterface usbInterface = mUsbDevice.getInterface(0);
                for (int i = 0; i < usbInterface.getEndpointCount(); i++) {
                    final UsbEndpoint usbEndpoint = usbInterface.getEndpoint(i);
                    if (usbEndpoint.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) {
                        if (usbEndpoint.getDirection() == UsbConstants.USB_DIR_OUT) {
                            mUsbDeviceConnection = mUsbManager.openDevice(mUsbDevice);
                            if (mUsbDeviceConnection != null) {

                                mUsbDeviceConnection.claimInterface(usbInterface, true);

                                new Thread(new Runnable() {
                                    @Override
                                    public void run() {
                                        EscCommand esc = new EscCommand();
                                        esc.addInitializePrinter();
                                        esc.addOpenCommand();
                                        Vector<Byte> datas = esc.getCommand(); // 发送数据
                                        byte[] bytes = GpUtils.ByteTo_byte(datas);
                                        int b = mUsbDeviceConnection.bulkTransfer(usbEndpoint, bytes, bytes.length, 3000);
                                        Elog.e("Printer", "打开钱箱成功 ----> " + datas.toString() + " 命令长度 ----> " + b);

                                    }
                                }).start();
                            }

                            break;
                        }
                    }
                }
            } else {
                ToastUtil.makeText(mContext, "打印机已断开,请检查！", true);
            }
        }


    }

    /**
     * 拼写账单模板
     */
    private void addBillTemp(EscCommand esc, PrintEntity printEntity) {


        // 店铺名称
        esc.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);
        if (!AppUtil.isBaoYingPos()) {
            esc.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.ON, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
        } else {
            esc.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
        }
        esc.addText(printEntity.getShopName()); // 打印文字
        esc.addPrintAndLineFeed();

        // 分割线
        esc.addText(PRINT_LINE);

        // 头部信息
        esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
        if (!AppUtil.isBaoYingPos()) {
            esc.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
        }
        esc.addText("单号：" + printEntity.getSerialNo());
        esc.addPrintAndLineFeed();
        esc.addText("操作时间：" + AppDateUtil.getTimeStamp(System.currentTimeMillis(), AppDateUtil.YYYY_MM_DD_HH_MM));
        esc.addPrintAndLineFeed();
        esc.addText("收银员：" + printEntity.getWaiter());
        esc.addPrintAndLineFeed();
        esc.addText("收银机号：" + DeviceIdUtils.getDeviceId());
        esc.addPrintAndLineFeed();

        // 分割线
        esc.addText(PRINT_LINE);

        // 商品头信息
        esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
        esc.addText("商品名          单价  数量  金额");
        esc.addPrintAndLineFeed();

        // 分割线
        esc.addText(PRINT_LINE);

        // 商品信息
        int goodsTotalNum = 0;
        List<PrintSettleEntity> goodsList = printEntity.getGoodsList();
        if (!ListUtil.isListEmpty(goodsList)) {

            for (int i = 0; i < goodsList.size(); i++) {

                PrintSettleEntity settleEntity = goodsList.get(i);

                // 按照字节长度拆分商品名称
                String[] goodsNames = SubByteString.getSubStrings(String.format("%s.%s", i + 1, settleEntity.getGoodsName()), PRINT_GOODS_NAME_LENGTH);

                // 打印商品名称
                if (goodsNames != null && goodsNames.length > 0) {
                    esc.addText(compStringToLength(goodsNames[0], PRINT_GOODS_NAME_LENGTH, true));
                } else {
                    esc.addText(compStringToLength(String.format("%s.%s", i + 1, settleEntity.getGoodsName()), PRINT_GOODS_NAME_LENGTH, true));
                }

                // 单价
                esc.addText(compStringToLength(getFormattedMoney(settleEntity.getGoodsPrice()), PRINT_GOODS_PRICE_LENGTH, false));

                // 数量
                esc.addText(compStringToLength(settleEntity.getGoodsCount(), PRINT_GOODS_COUNT_LENGTH, false));
                goodsTotalNum += Integer.parseInt(settleEntity.getGoodsCount());

                // 金额
                esc.addText(compStringToLength(getFormattedMoney(settleEntity.getTotalPrice()), PRINT_GOODS_PRICE_LENGTH, false));

                // 看当前商品名称是否超长，换行打印剩余的商品名称
                if (goodsNames == null || goodsNames.length == 0) {
                    esc.addPrintAndLineFeed();
                } else if (goodsNames.length > 1) {
                    for (int j = 1; j < goodsNames.length; j++) {
                        esc.addText("" + goodsNames[j]);
                        esc.addPrintAndLineFeed();
                    }
                }

            }

            if (!AppUtil.isBaoYingPos()) {
                esc.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
            }
            esc.addText(PRINT_LINE);

        }

        esc.addSetHorAndVerMotionUnits((byte) PRINT_UNIT, (byte) 0);

        // 设置商品数量以及商品金额总计
        esc.addText(compStringToLength("商品数量：" + goodsTotalNum, PRINT_MAX_LENGTH / 2, true));
        esc.addText(compStringToLength("总计：" + getFormattedMoney(printEntity.getTotalPrice()), PRINT_MAX_LENGTH / 2, false));
        esc.addPrintAndLineFeed();

        // 设置优惠活动
        List<PrintDiscountEntity> discountList = printEntity.getDiscountList();
        if (!ListUtil.isListEmpty(discountList)) {
            for (int i = 0; i < discountList.size(); i++) {
                PrintDiscountEntity discountEntity = discountList.get(i);
                esc.addText(compStringToLength(StringUtils.getString(discountEntity.getName()), PRINT_MAX_LENGTH / 2, true));
                esc.addText(compStringToLength(formatDiscount(discountEntity.getAmount()), PRINT_MAX_LENGTH / 2, false));
                esc.addPrintAndLineFeed();
            }
        }

        // 分割线
        if (!AppUtil.isBaoYingPos()) {
            esc.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
        }
        esc.addText(PRINT_LINE);

        // 支付方式
        boolean useBalancePay = false;
        List<PrintPayTypeEntity> payTypeList = printEntity.getPayTypeList();
        if (!ListUtil.isListEmpty(payTypeList)) {
            for (int i = 0; i < payTypeList.size(); i++) {

                PrintPayTypeEntity payTypeEntity = payTypeList.get(i);
                esc.addText(compStringToLength(payTypeEntity.getName(), PRINT_MAX_LENGTH / 2, true));
                esc.addText(compStringToLength("￥" + getFormattedMoney(payTypeEntity.getAmount()), PRINT_MAX_LENGTH / 2, false));
                esc.addPrintAndLineFeed();

                if (!useBalancePay && BillUtil.PAY_TYPE_BALANCE.equals(payTypeEntity.getType())) {
                    useBalancePay = true;
                }
            }
            esc.addText("\n");
        }

        esc.addText(PRINT_LINE);

        // 会员信息
        if (AppConstants.CONFIG_SHOW_MEMBER_INFO && !StringUtils.isEmpty(printEntity.getBillingUser()) && useBalancePay) {
            esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
            esc.addText(String.format("会员：%s(%s)", printEntity.getMemberName(), printEntity.getMemberPhone()));
            esc.addPrintAndLineFeed();
            esc.addText("余额：" + StringUtils.getFormattedMoneyWithUnit(printEntity.getCurrentAmount()));
            esc.addPrintAndLineFeed();
            esc.addText("积分：" + BigDecimalUtil.getNumber(printEntity.getIntegral()));
            esc.addPrintAndLineFeed();

        }

        // 客服电话
        if (AppConstants.CONFIG_SHOW_SHOP_PHONE && !StringUtils.isEmpty(AppConstants.TEMP_SHOP_PHONE)) {
            esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
            esc.addText("客服电话：" + AppConstants.TEMP_SHOP_PHONE);
            esc.addPrintAndLineFeed();

        }

        // 门店地址
        if (AppConstants.CONFIG_SHOW_SHOP_ADDRESS && !StringUtils.isEmpty(AppConstants.TEMP_SHOP_ADDRESS)) {
            esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
            esc.addText("门店地址：" + AppConstants.TEMP_SHOP_ADDRESS);
            esc.addPrintAndLineFeed();
            esc.addPrintAndLineFeed();

        }

        //购买须知
        AppRepository repository = new AppRepository();
        if (AppConstants.CONFIG_SHOW_BUY_NOTE && !StringUtils.isEmpty(repository.getBuyNote())) {
            esc.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);
            esc.addText("购买须知！");
            esc.addPrintAndLineFeed();
            esc.addText(repository.getBuyNote());
            esc.addPrintAndLineFeed();
            esc.addPrintAndLineFeed();
        }


        // 圣旦云
        esc.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);
        esc.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
        esc.addText("圣旦云提供技术支持"); // 打印文字

        esc.addPrintAndLineFeed();
        esc.addPrintAndLineFeed();
        esc.addPrintAndLineFeed();
        esc.addPrintAndLineFeed();
        esc.addCutPaper();

    }

    private String formatDiscount(String moneyAmount) {
        if (!TextUtils.isEmpty(moneyAmount)) {
            double parseDouble = Double.parseDouble(new BigDecimal(moneyAmount).toPlainString());
            if (parseDouble >= 0) {
                return String.format("-￥%s", new DecimalFormat("0.00").format(parseDouble));
            } else {
                return String.format("+￥%s", new DecimalFormat("0.00").format(Math.abs(parseDouble)));
            }
        } else {
            return String.format("-￥%s", getFormattedMoney("0"));
        }
    }

    /**
     * 拼写交班模板
     */
    private void addOffWordTemp(EscCommand esc, OffWorkTicketEntity offWorkTicketEntity) {


        // 店铺名称
        esc.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);
        if (!AppUtil.isBaoYingPos()) {
            esc.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.ON, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
        } else {
            esc.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
        }
        esc.addText("圣旦收银交班单"); // 打印文字
        esc.addPrintAndLineFeed();
        esc.addPrintAndLineFeed();

        esc.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
        // 头部信息
        esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
        esc.addText(compStringToLength(String.format("门店：%s", AppConstants.TEMP_SHOP_NAME), PRINT_MAX_LENGTH, true));
        esc.addPrintAndLineFeed();
        esc.addText(compStringToLength(String.format("收银员：%s", StringUtils.get(offWorkTicketEntity.getUserName())), PRINT_MAX_LENGTH, true));
        esc.addPrintAndLineFeed();
        esc.addText(String.format("在班时间：%s 至 %s", offWorkTicketEntity.getStartTime(), offWorkTicketEntity.getEndTime()));
        esc.addPrintAndLineFeed();

        esc.addText(PRINT_LINE);
        esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
        esc.addText(compStringToLength("类型", PRINT_SALE_TYPE_LENGTH, true));
        esc.addText(compStringToLength("数量", PRINT_GOODS_COUNT_LENGTH, true));
        esc.addText(compStringToLength("应收金额", PRINT_SALE_PRICE_LENGTH, false));
        esc.addText(compStringToLength("实收金额", PRINT_SALE_PRICE_LENGTH, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("商品售卖:", PRINT_SALE_TYPE_LENGTH, true));
        esc.addText(compStringToLength(String.format("%s单", offWorkTicketEntity.getGoodsNum()), PRINT_GOODS_COUNT_LENGTH, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getReceivableGoodsAmount(), PRINT_SALE_PRICE_LENGTH, false));
        esc.addText(compStringToLength(offWorkTicketEntity.getActualGoodsAmount(), PRINT_SALE_PRICE_LENGTH, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("服务售卖:", PRINT_SALE_TYPE_LENGTH, true));
        esc.addText(compStringToLength(String.format("%s次", offWorkTicketEntity.getAppointmentNum()), PRINT_GOODS_COUNT_LENGTH, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getReceivableAppointmentAmount(), PRINT_SALE_PRICE_LENGTH, false));
        esc.addText(compStringToLength(offWorkTicketEntity.getActualAppointmentAmount(), PRINT_SALE_PRICE_LENGTH, false));
        esc.addPrintAndLineFeed();


        esc.addText(compStringToLength("计次卡售", PRINT_SALE_TYPE_LENGTH, true));
        esc.addText(compStringToLength(String.format("%s张", offWorkTicketEntity.getTimesCardNum()), PRINT_GOODS_COUNT_LENGTH, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getReceivableTimesCardAmount(), PRINT_SALE_PRICE_LENGTH, false));
        esc.addText(compStringToLength(offWorkTicketEntity.getActualTimesCardAmount(), PRINT_SALE_PRICE_LENGTH, false));
        esc.addText("卖:");
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("商品退货:", PRINT_SALE_TYPE_LENGTH, true));
        esc.addText(compStringToLength(String.format("%s个", offWorkTicketEntity.getGoodsReturnNum()), PRINT_GOODS_COUNT_LENGTH, true));
        esc.addText(compStringToLength("", PRINT_SALE_PRICE_LENGTH, false));
        esc.addText(compStringToLength(offWorkTicketEntity.getActualGoodsReturnAmount(), PRINT_SALE_PRICE_LENGTH, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("计次卡退", PRINT_SALE_TYPE_LENGTH, true));
        esc.addText(compStringToLength(String.format("%s张", offWorkTicketEntity.getTimesCardReturnNuM()), PRINT_GOODS_COUNT_LENGTH, true));
        esc.addText(compStringToLength("", PRINT_SALE_PRICE_LENGTH, false));
        esc.addText(compStringToLength(offWorkTicketEntity.getActualTimesCardReturnAmount(), PRINT_SALE_PRICE_LENGTH, false));
        esc.addText("卡:");
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("会员余额", PRINT_SALE_TYPE_LENGTH, true));
        esc.addText(compStringToLength(String.format("%s次", offWorkTicketEntity.getBalanceNum()), PRINT_GOODS_COUNT_LENGTH, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getBalanceAmount(), PRINT_SALE_PRICE_LENGTH, false));
        esc.addText(compStringToLength(offWorkTicketEntity.getBalanceAmount(), PRINT_SALE_PRICE_LENGTH, false));
        esc.addText("充值:");
        esc.addPrintAndLineFeed();

        esc.addText(PRINT_LINE);
        esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
        esc.addText(compStringToLength("应收总额:", PRINT_MAX_LENGTH / 2, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getReceivableAmount(), PRINT_MAX_LENGTH / 2, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("商品折扣:", PRINT_MAX_LENGTH / 2, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getGoodsDiscount(), PRINT_MAX_LENGTH / 2, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("议价金额:", PRINT_MAX_LENGTH / 2, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getBargainAmount(), PRINT_MAX_LENGTH / 2, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("赠送优惠:", PRINT_MAX_LENGTH / 2, true));
        esc.addText(compStringToLength(StringUtils.get(offWorkTicketEntity.getPresentDiscount()), PRINT_MAX_LENGTH / 2, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("会员折扣:", PRINT_MAX_LENGTH / 2, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getMemberDiscount(), PRINT_MAX_LENGTH / 2, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("优惠活动:", PRINT_MAX_LENGTH / 2, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getActivityDiscount(), PRINT_MAX_LENGTH / 2, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("优惠券\\体验券:", PRINT_MAX_LENGTH / 2, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getTicketDiscount(), PRINT_MAX_LENGTH / 2, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("积分抵现:", PRINT_MAX_LENGTH / 2, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getIntegralAmount(), PRINT_MAX_LENGTH / 2, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("抹零:", PRINT_MAX_LENGTH / 2, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getMlAmount(), PRINT_MAX_LENGTH / 2, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("退换货金额:", PRINT_MAX_LENGTH / 2, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getReturnAmount(), PRINT_MAX_LENGTH / 2, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("实收金额:", PRINT_MAX_LENGTH / 2, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getActualAmount(), PRINT_MAX_LENGTH / 2, false));
        esc.addPrintAndLineFeed();

        esc.addText(PRINT_LINE);

        esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
        esc.addText(compStringToLength("结算方式", PRINT_SALE_PRICE_LENGTH, true));
        esc.addText(compStringToLength("实收金额", PRINT_SALE_PRICE_LENGTH, true));
        esc.addText(compStringToLength("实盘金额", PRINT_SALE_PRICE_LENGTH, true));
        esc.addText(compStringToLength("溢缺", 5, true));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("现金:", PRINT_SALE_PRICE_LENGTH, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getCashAmount() + " ", PRINT_SALE_PRICE_LENGTH, false));
        esc.addText(compStringToLength(offWorkTicketEntity.getCashFirm(), PRINT_SALE_PRICE_LENGTH, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getOverAndAhort(), 5, true));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("银行卡:", PRINT_SALE_PRICE_LENGTH, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getCardAmount() + " ", PRINT_SALE_PRICE_LENGTH, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("支付宝:", PRINT_SALE_PRICE_LENGTH, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getAliAmount() + " ", PRINT_SALE_PRICE_LENGTH, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("微信:", PRINT_SALE_PRICE_LENGTH, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getWechatAmount() + " ", PRINT_SALE_PRICE_LENGTH, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("会员余额:", PRINT_SALE_PRICE_LENGTH, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getMemberAmount() + " ", PRINT_SALE_PRICE_LENGTH, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("计次卡:", PRINT_SALE_PRICE_LENGTH, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getTimeCardAmount() + " ", PRINT_SALE_PRICE_LENGTH, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength(String.format("%s积分抵现",
                StringUtils.getWholeNumber(BigDecimalUtil.getNumber(offWorkTicketEntity.getIntegralMoney()))), PRINT_SALE_PRICE_LENGTH, true));
        esc.addText(compStringToLength(offWorkTicketEntity.getIntegralAmount() + " ", PRINT_SALE_PRICE_LENGTH, false));
        esc.addPrintAndLineFeed();


        esc.addPrintAndLineFeed();
        esc.addPrintAndLineFeed();

        // 圣旦云
        esc.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);
        if (!AppUtil.isBaoYingPos()) {
            esc.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
        }
        esc.addText("圣旦云提供技术支持"); // 打印文字

        esc.addPrintAndLineFeed();
        esc.addPrintAndLineFeed();
        esc.addPrintAndLineFeed();
        esc.addPrintAndLineFeed();
        esc.addPrintAndLineFeed();
        esc.addPrintAndLineFeed();

    }


    /**
     * 储值模板
     */
    private void addRechargeTemp(EscCommand esc, RechargeDetailEntity detailEntity) {


        // 店铺名称
        esc.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);
        if (!AppUtil.isBaoYingPos()) {
            esc.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.ON, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
        } else {
            esc.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
        }
        esc.addText(AppConstants.TEMP_SHOP_NAME); // 打印文字
        esc.addPrintAndLineFeed();

        // 分割线
        esc.addText(PRINT_LINE);

        // 头部信息
        esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
        if (!AppUtil.isBaoYingPos()) {
            esc.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
        }
        esc.addText("单号：" + StringUtils.get(detailEntity.getOrderCode()));
        esc.addPrintAndLineFeed();
        esc.addText("操作时间：" + AppDateUtil.getTimeStamp(System.currentTimeMillis(), AppDateUtil.YYYY_MM_DD_HH_MM));
        esc.addPrintAndLineFeed();
        esc.addText("收银员：" + AppConstants.TEMP_USER_NAME);
        esc.addPrintAndLineFeed();
        esc.addText("收银机号：" + StringUtils.get(detailEntity.getPosCode()));
        esc.addPrintAndLineFeed();

        esc.addText(PRINT_LINE);
        esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
        esc.addText(compStringToLength("充值金额:", PRINT_MAX_LENGTH / 2, true));
        esc.addText(compStringToLength(getFormattedMoney(detailEntity.getStoreAmount()),
                PRINT_MAX_LENGTH / 2, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("充值方式:", PRINT_MAX_LENGTH / 2, true));
        esc.addText(compStringToLength(StringUtils.get(detailEntity.getStoreType()), PRINT_MAX_LENGTH / 2, false));
        esc.addPrintAndLineFeed();

        esc.addText(compStringToLength("会员余额:", PRINT_MAX_LENGTH / 2, true));
        esc.addText(compStringToLength(getFormattedMoney(detailEntity.getMemberBlance()), PRINT_MAX_LENGTH / 2, false));
        esc.addPrintAndLineFeed();

        esc.addText(PRINT_LINE);

        // 会员信息
        esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
        esc.addText(String.format("会员：%s(%s)", StringUtils.get(detailEntity.getMemberName()), StringUtils.get(detailEntity.getMemberPhone())));
        esc.addPrintAndLineFeed();
        esc.addText("余额：" + StringUtils.getFormattedMoneyWithUnit(detailEntity.getMemberBlance()));
        esc.addPrintAndLineFeed();
        esc.addText("积分：" + BigDecimalUtil.getNumber(detailEntity.getIntegral()));
        esc.addPrintAndLineFeed();


        // 客服电话
        if (AppConstants.CONFIG_SHOW_SHOP_PHONE && !StringUtils.isEmpty(AppConstants.TEMP_SHOP_PHONE)) {
            esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
            esc.addText("客服电话：" + AppConstants.TEMP_SHOP_PHONE);
            esc.addPrintAndLineFeed();

        }

        // 门店地址
        if (AppConstants.CONFIG_SHOW_SHOP_ADDRESS && !StringUtils.isEmpty(AppConstants.TEMP_SHOP_ADDRESS)) {
            esc.addSelectJustification(EscCommand.JUSTIFICATION.LEFT);
            esc.addText("门店地址：" + AppConstants.TEMP_SHOP_ADDRESS);
            esc.addPrintAndLineFeed();

        }

        //购买须知
        AppRepository repository = new AppRepository();
        if (AppConstants.CONFIG_SHOW_BUY_NOTE && !StringUtils.isEmpty(repository.getBuyNote())) {
            esc.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);
            esc.addText("购买须知！");
            esc.addPrintAndLineFeed();
            esc.addText(repository.getBuyNote());
            esc.addPrintAndLineFeed();
        }


        // 圣旦云
        esc.addPrintAndLineFeed();
        esc.addPrintAndLineFeed();
        esc.addSelectJustification(EscCommand.JUSTIFICATION.CENTER);
        esc.addSelectPrintModes(EscCommand.FONT.FONTA, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF, EscCommand.ENABLE.OFF);
        esc.addText("圣旦云提供技术支持"); // 打印文字

        esc.addPrintAndLineFeed();
        esc.addPrintAndLineFeed();
        esc.addPrintAndLineFeed();
        esc.addPrintAndLineFeed();
        esc.addCutPaper();
    }


    /**
     * 补齐字符串到指定长度
     *
     * @param attr        原始字符串
     * @param length      指定长度
     * @param gravityLeft 是否左对齐
     * @return
     */
    private String compStringToLength(String attr, int length, boolean gravityLeft) {
        try {
            int attrLength = attr.getBytes("GB2312").length;
            int diffLength = length - attrLength;
            StringBuilder builder = new StringBuilder();
            if (gravityLeft) {
                builder.append(attr);
            }
            for (int i = 0; i < diffLength; i++) {
                builder.append(" ");
            }
            if (!gravityLeft) {
                builder.append(attr);
            }
            return builder.toString();

        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
        return null;
    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        mContext.unregisterReceiver(mUsbDeviceReceiver);
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    private void destroy() {
        if (mUsbDeviceConnection != null) {
            mUsbDeviceConnection.close();
            mUsbDeviceConnection = null;
        }
    }

    public static void openDrawer(Context context) {
        Intent intent = new Intent();
        intent.setAction(PrinterService.ACTION_DO_OPEN_DRAWER);
        intent.putExtra(PrinterService.PRINT_FLAVOR, BuildConfig.FLAVOR);
        context.sendBroadcast(intent);
    }

    public static void doPrintTicket(Context context, PrintEntity printEntity, int printCount) {
        Intent intent = new Intent();
        intent.setAction(PrinterService.ACTION_DO_PRINT);
        intent.putExtra(PrinterService.ACTION_DO_PRINT, printEntity);
        intent.putExtra(PrinterService.PRINT_COUNT, printCount);
        intent.putExtra(PrinterService.PRINT_FLAVOR, BuildConfig.FLAVOR);
        context.sendBroadcast(intent);
    }

    public static void doPrintOffWordTicket(Context context, OffWorkTicketEntity offWorkTicketEntity) {
        Intent intent = new Intent();
        intent.setAction(PrinterService.ACTION_DO_PRINT_OFFWORD);
        intent.putExtra(PrinterService.ACTION_DO_PRINT_OFFWORD, offWorkTicketEntity);
        intent.putExtra(PrinterService.PRINT_COUNT, 1);
        intent.putExtra(PrinterService.PRINT_FLAVOR, BuildConfig.FLAVOR);
        context.sendBroadcast(intent);
    }

    public static void doPrintRechargeTicket(Context context, RechargeDetailEntity rechargeDetailEntity, int printCount) {
        Intent intent = new Intent();
        intent.setAction(PrinterService.ACTION_DO_PRINT_RECHARGE);
        intent.putExtra(PrinterService.ACTION_DO_PRINT_RECHARGE, rechargeDetailEntity);
        intent.putExtra(PrinterService.PRINT_COUNT, printCount);
        intent.putExtra(PrinterService.PRINT_FLAVOR, BuildConfig.FLAVOR);
        context.sendBroadcast(intent);
    }
}
